{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Logistic Regression exercise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "\n",
    "%matplotlib inline\n",
    "plt.rcParams['figure.figsize'] = (15., 12.) # set default size of plots\n",
    "plt.rcParams['image.interpolation'] = 'nearest'\n",
    "plt.rcParams['image.cmap'] = 'gray'\n",
    "\n",
    "# Some more magic so that the notebook will reload external python modules;\n",
    "%load_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Read the data for you\n",
    "data = pd.read_csv('./DSVC/datasets/MNIST.csv',header=0).values # change the path by yourself\n",
    "imgs = data[0::,1::]\n",
    "labels = data[::,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 70 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Visualize some examples from the dataset.\n",
    "# We show a few examples of training images from each class.\n",
    "classes = range(10)\n",
    "num_classes = len(classes)\n",
    "samples_per_class = 7\n",
    "for y, cls in enumerate(classes):\n",
    "    idxs = np.flatnonzero(labels == y)\n",
    "    idxs = np.random.choice(idxs, samples_per_class, replace=False)\n",
    "    for i, idx in enumerate(idxs):\n",
    "        plt_idx = i * num_classes + y + 1\n",
    "        plt.subplot(samples_per_class, num_classes, plt_idx)\n",
    "        plt.imshow(imgs[idx].reshape(28,28).astype('uint8'))\n",
    "        plt.axis('off')\n",
    "        if i == 0:\n",
    "            plt.title(cls)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Binary classification\n",
    "We use the Logistic Regression to classification handwritten digits wheather it's zero or not. If the handwritten digits is '0' , then the label is 0, otherwise, the label is 1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(28000L, 785L)\n",
      "(14000L, 785L)\n"
     ]
    }
   ],
   "source": [
    "# transform the labels to binary\n",
    "for i in xrange(len(labels)):\n",
    "    if labels[i] != 0:\n",
    "        labels[i] = 1\n",
    "        \n",
    "# 2/3 training set\n",
    "# 1/3 test set\n",
    "split_index = len(labels) * 2 / 3\n",
    "X_train = imgs[:split_index]\n",
    "y_train = labels[:split_index]\n",
    "X_test = imgs[split_index:]\n",
    "y_test = labels[split_index:]\n",
    "\n",
    "X_train = np.hstack([X_train, np.ones((X_train.shape[0], 1))])\n",
    "X_test = np.hstack([X_test, np.ones((X_test.shape[0], 1))])\n",
    "\n",
    "print X_train.shape\n",
    "print X_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train_feats = None # choose and extract features\n",
    "X_test_feats = None # choose and extract features\n",
    "X_train_feats = (X_train - np.mean(X_train)) / np.std(X_train)\n",
    "X_test_feats = (X_test - np.mean(X_test)) / np.std(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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OTm5wbxhtbW1WL58OVwuFy5cuGBmk4lapaamps0uYAEscEBNVVV06NDB+DsqKgq33npro9fV1tZi//79WLhwIf79738Hs4lE7ZLp+9zPPPOMz9csW7YMDocDt912G4NNtnHo0KE2Xb7p4X755Zfx+9//Hvv372/03P79+zFy5EjMnDkTx48fN6F1RG1n165dbbp80zfLz58/jzVr1iA/Px/x8fGYMmUKDh06hMrKShQVFaGqqsrsJhK1S5b54UigCX84QkHU0r7dpUsXpKWlYdu2bS1el799m+EmCgAr9m3T97mJqG0w3EQ2xfm5iWyKIzeRTTHcRDbFcBPZFMNNZFOcn5soAKzYt9vFyJ2ZmYmamhrMmTPH7KYQtRvt5gq15ORklJWVeb1by+U4clMwWXHkbjfhbimGm4LJin27XWyWE1HLMdxENsVwE9mUpcOtKAoOHjyIqqoquN1uOJ3OBvdbI2rPFixYgJMnT2LlypVYsGAB0tLS8Nhjj+GVV15BZWUlKisrsWbNGtx3331XtgKr3v61a9eu8uc//1l0XW9QBQUFEhEREbDbv7JYgaiW9O3Y2FiZM2eOqKoqmqaJqqoNyvPYkSNHZPv27bJ9+/Yr6tuW/QCWLFnSKNieyszMZLhZlip/+/WwYcNk165doqqq3H333ZKbmytut1tWrVolqqrKunXrJDc3V0aOHCkxMTGt6tuW/AA6duwoR44cMcIsIg3+PWfOHIabZany1R8HDBggubm5xiQceXl5LZ6MwBbhfv75572O2rquy759+xhulqXKV3+cMWOGscm9fft26dixY5uH23IH1BwOB/74xz8af2/duhVnz541sUVErTd48GDj3x999BGio6MRGxvbtiu10rfb8uXLjdFZ0zTJzc0VADJlyhSO3CxLl7d+OGrUKImOjhYA0r17d1m/fn2TB89mzpxp783ykpISI8Br1qwRADJkyBD54YcfGuxzM9wsq5W/waxfO3fuFBERTdNk9+7dcscdd9h7s9yjoqICffr0QX5+Pq655hrjcRHBqVOnTGwZUWAMGzYMv/vd73Dq1CkMHjwY8+bNC+wKrPTtVn/kvnDhglRUVDQ6mJabmytxcXEcuVmWqqb64NGjR/0ajW+55RY5efKknD9/XlJSUuw/coeFhSEuLq7BY//617/wzDPP4MSJEya1ish/R48exW233ebzdeXl5Th27Bg6duyIhISEwDXA7G+3+pWdne319Ndjjz0mP/+sLqD7JSxWIKqpPjht2jQ5c+aMDBs2zGs/nT59unFRy65duyQ8PNyeB9QGDRokixYtktraWiPU69atkwkTJkhISEiLDlaY/X826+oqb/3wiSeekIsXL4qmabJ+/XoZOHCgUadPnxaRSwfUvv76axk7dmxA+zZv1kAUAM317ccffxyzZ8/GL37xCyiKgvqZKykpwd///nfs2rULR48e9Wtd/vZthpsoAHz17a5duyI8PBzJycno27cvevXqhRUrVuCnn37C+fPnW7QuhpvhpiCyYt+27NFyImodhpvIphhuIptiuIlsivNzE9kUR24im2K4iWyK4SayKYabyKY4PzdRAFixb3PkJrIphpvIpiwd7kcffRRFRUUoKirCokWLzG4OUbti6XBPnz4d/fr1w/Tp0/G///0P/fr1w/XXX4/KykpMnz7d7OYRWZsV7lbhrfLy8qSurk6qqqqkrq5OampqpLy8XHJycqS0tFRee+013omFZYlqad8GIC6XS+pzuVwBvROLpT+AsLCwBvdRKywslF//+tcCQCZOnCiLFy9muFmWqJb0a6fT2SjYHm63++oI99y5cxuE299vNoabFey6ktHa7XaL0+k0nnO73SLiewT3u01W/ACSkpJkz549UltbK1u3bpXJkydLRUWF1NbWSlFREcPNslz5M1pfzku/tW+4x40bJ99++63oui7l5eUSEREhACQ1NbVFATf7/2zW1VX+jtYijUfsqyLciYmJUlZWZgT71ltvbfB8amqqlJeXS21trcydO5fhZlmmvPVDz6a2h7dQ1x/dmwt/uwx3YmKifP75516D7akRI0aIrutSW1sr9913H8PNskT5M2I3F9imvghsEe7MzExRVVV0XW/29Fb9Wr16tVy8eFFmz57NcLNML2+jsIe3kbqpo+a+jpj726ag/nDEm4SEBISEXLqeZu3atX69p6KiAqGhoVi8eDG++eYbvPXWW23ZRKIWcTqdjf4uLi5u8Jjb7W7yvQsXLgxMI8z8dvPU/v37jfPYnTp18mvkjo2NldOnT0t1dbX069ePIzfL1Gqqj16+me3N5afHfPV9v9tk9gcAwJgbrLkJ0y6vjh07yoYNG+Ts2bPcLGeZXk31QafT2WzAPfvg9Tfhfe2Xt9twT5s2ze9wJycni67rDDfLEuWrv3r2r+uHuV5fNfjT9/1ukxU+gH/+85+i67qUlZVJfHy8z/+40NBQ2bBhg6iqKsuWLWO4WaaXv4OSl74qIoG/ttwSvwrbt28fAMDhcOD5559Hhw4dmnxdaGgoHA4H3njjDTzwwAOoqKjgr8OoXXO5XG22bEscLd++fTs2btyI+++/H1lZWairq8O5c+dw8OBBvPnmmwCASZMmITU1FVlZWQCAN998k7/xJmqGJcL9ySef4IEHHsCwYcPQs2dPTJ482Xhu+fLlDV5bWVmJnJwcbN26FZ999lmQW0rUflhuCt9Zs2bh9ttvR3R0NO644w4AwPHjx/Haa68BADZt2oSDBw/6XJfwBokURK25QWL9DCqK727rb9+2XLgDheGmYGpN33Y6nY0uaCkuLsaOHTua3Cf3t29b4oAa0dWsuLgYI0aMMK5May7YLcGRmygArNi3OXIT2RSn8CWyKY7cRDbFcBPZFMNNZFMMN5FNMdxENsX5uYkCwIp9myM3kU0x3EQ2ZelwDx8+HJqmobKyEjNnzsTw4cPNbhJRu2HJa8tjYmKwatUqDB06FN26dTMeP3fuHL777jssWbIEK1eubHYZ3OemYOI+t5/S09Nx9913o1u3bqiursaxY8cAAN26dUPfvn2xePFiFBYWIiYmxuSWEvnnrrvuQl5eHnRdh6Zp0HUdp06dQl5eHhwOR9us1Go3kVMURb744gtRVVVUVZWHHnpIrrnmGpkxY4ZommY8rqqqLF26VH7+xuQNElmmVnN9+umnnzb6bv3/9fy7qqrK59x3V9K3LfMBeGrmzJkNAnz58/Pnz5cjR44YH9BDDz3EcLNML2/9efPmzaJpmhHgjIwM47mpU6fKkiVLRNd10TTN7/v2+90mK3wAnrrxxhulsrLSCLa3W72mpaUZ4d6yZQvDzTK9muqDGRkZxui8du1ar/3+wIEDoqqqzJ07V6ZOnSoOh8Ne4e7du7cxIquqKp9++qn06dOnyddGRUVJQUGBaJomJ06ckMGDBzPcLFOrqX66Z88e0XVdVqxY0WxYHQ6HzJ07V/Ly8kTTNFmyZElAwm2ZA2oTJ05Enz59jL/nzZtnHEi7XHV1NXJycgBcOrJ+7bXXBqWNRC31c/CbdfDgQeM23SKCG264ISDrtsStjdPT0/Hcc88Zf8+bNw/vvfdes+/ZuXMnQkJCoOu6X3eMJDJDS/umoii47rrrArNyszddADQ4Op6Tk+PXQYXs7Gxjf+aDDz7gZjnL1GqqjzocDjl16pRommYcNMvLy5NRo0bJLbfcYlReXp6cPHnSeM2ePXvss8/d0nDHxMTI3r17jXCPGjWK4WaZWt76akJCgmzatKnZU2GX/2+gwm2JzXJFUYzNl9mzZ/t8/b333ouUlBRulpPlHT9+HOPGjcOwYcPgcDgQExODsWPHNnjNqlWrAADx8fGYN28eoqKiEBkZiZqamtat3ArfbvVHbm+v8dS2bdvk3Llzxjddbm6uREZGcuRmmVq++q0/1adPH6msrBRN0yQrK8s+R8t9iYmJwcMPP4zU1FRERkYCAFavXo0nn3yy9d9wRBZw7NgxlJeXQ1EUZGRktHp5ltgs9yU7OxtTpkxBSkqK51sSmzZtwtSpU01uGVHgiQiuv/76Vi/HEuGuv8/tdruRn59vPLd06VLj35597NWrVzPYZFuKouDGG29s9XIsEe56+y0YOnQohg4d2uA5j3feeQfPPvssSktLg95GomCpn4fWsMQ+97Fjx1BdXd3kc9XV1Th8+DAWLVqEe+65B//973+5j022tWrVKoSEhATkDJAlRu7f/OY3uPfee5GQkIChQ4fivvvuA3Bpv3r9+vXYsmWLyS0kCh5d1yEicDgcfs1F740l78QSCMI7sVAQBapvZ2RkID8/H7qu480338TEiRMbvcbfvm2JzXIiuqSgoABlZWUQkQYHlq8ER26iALBi3+bITWRTnJ+byKY4chPZFMNNZFMMN5FNMdxENsUpfIkCwIp9myM3kU0x3EQ2xXAT2ZRlw33u3DmvkxIQkW+WDHevXr2gKAp69OiBlJQUdO3a1ewmEbU7lvvhSI8ePbB161YMGjTIeKywsBArV67EO++84/e6eLScgulKjpY7HA6MHDnS+PvMmTNYv369z/f53betdvvXyZMni67rjaqurk727t3rdXLAy8vsW92yrq7yp09GRkbKpEmTZN26dVJRUSHff/+9MTmBpmlSW1srS5Yssd8sn57auXNnk+H21CeffCKxsbEMN8tS5as/Zmdny6FDh4wge6YOaqq+/vprGTBgwNVz33KPm2++GU888YTZzSBqkRtuuAF9+/b167U9evRA9+7dW71Oy4b7m2++QV5eHl5//fVG91B77LHH0K9fP5NaRtRy58+fR0lJiV+vDQ8Px9q1a1u/Uittutx5553yww8/iK7rsnz5cuPx8PBwWbp0qdTV1Rmb52lpadwsZ1mmfPVtABIRESEZGRny/vvvN7tZrmmaVFZW2mufe9KkSUZ4u3bt2uj5pUuXGs8XFxcz3CzLlD/hBiBdunSR48ePew336dOn5fDhw5KcnHx17XPPmjULmzdvBgAkJydjxIgRJreIqGWqqqqQkJCA22+/vdFz+fn5GDlyJPr374/PPvus1etqV+Gur3v37ujdu7fZzSC6Irt378avfvUrvPjiizh58iQURcG4ceMwc+bMgK2j3Yb7448/RkFBgdnNIGokLS3Nr9ft3bsX8+bNQ05ODsrLy6HrOh588EFMmTIlIO1ot+E+c+aM1ymIiMzy4IMPYsuWLdixYwdiYmL8es9LL72EV199FcClSQCfffZZOJ3O1jfGSgcdbrnlFikvLxdd1+Uvf/mLJCYmNnh+2rRpsn//ftF1vdmT/OABNVaQy9PvPAfKzpw5I1OnTpXo6GifZ4i2bdsmVVVVxkG1H3/8MSB923LXlu/cuRNDhgwBAFRUVGDChAkAgNGjR2PWrFkIDb108xiHw4FDhw55XY7w2nIKIk/fPnz4MJKSkozHy8rKmpy4UlEUiAiSk5PRqVOnBs/t27cPgwcP9rouf/u2JSYCrO/ixYvQNA0dOnRA79694Xa7zW4Skd/uvPNOZGVlYfLkyUhKSvI6z7Yn3Jf76quv8MILLwSmMWZsuviqjIwMqa2t9Xp9+aeffurz+nKzN9NYV1dd3v8SEhJk7Nix8t5778mBAwfk7NmzDc5ni0ijc9zHjh2Te++912c+/G2T5TbLPfbt24eUlJRGj5eWluKuu+7CiRMnmn2/cLOcgshX33Y6nYiPj0d4eDj++te/Nhi5V6xYgW+++QbFxcUoLy/3uS5/+7Zlw52UlITx48dj0aJFDR6///77sWnTJp/vZ7gpmKx491PLhru1GG4KJiv27XZ7npuImsdwE9kUw01kU5yfm8imOHIT2RTDTWRTDDeRTTHcRDbF+bmJAsCKfZsjN5FNMdxENsVwE9mUpcPtcrkgInC5XGY3hajdsWy4nU4nFixYYHYziNoty91myaOp2yvVH8E5mhP5YOataJoqp9Mpbrdb6nO5XNIUp9PJ2yyxLFH+9O2mKjQ0VOLi4iQrK0tKS0vlH//4R8Bus2S5kXvBggXGPZsXLlzY7Ka52+3GiBEjUFxcHJzGETVDURSkpKRg4MCBePfdd72+Li0tDb169cLYsWPRv39/DBgwABcvXkRYWFhgZvf0tOfnb52g8HWi3+12N7gZu2cusPr7357H6m+2K0rjc/rCi1goiBRFkY4dO2L37t1ISkpCt27dvL72woULOHPmDA4fPozS0lIUFRVh5MiReOSRR9CzZ0+cPXu22XX527ctE26n09kgsJePyG63GwsXLmzwmKftTY3eDDcFU/2+3bNnTyQmJjZ4vkePHujfvz/+85//4PTp0/jyyy+N58LDw7F7927s3r0b2dnZPtfld9+2yn5JfW6326/9Fc++eFOvN3sfjHV1lT/91VtlZmaKrusyceJEv17vb5sscSqs/pHv4uLiFk/NG5B5lYhM4pm4YNu2bQFdriXCXR/n3KarzejRo/Hhhx+isrIyoMu1RLh5sQpdzcLDw1FYWBjw5Voi3Fdq+PDhZjeBqFUcDgccDgfq6uoCvux2G26Xy9XgfDhRe3TbbbchJCQEuq4HfNntMtyXX3fOS1GpverduzdEBAUFBQFftiXCXf8cta+gNnU+nKi9GjJkCL777jtUVVUFfNmWCPeOHTuMfy9YsMBrwF0uV7MXuhC1NzExMfjiiy/w/fffB37hVjjR39SPRZrjdrub/dEIeBELK8jVXF/0Vr1795aqqip5+umnW/Q+f9tkiR+OFBcXo7i42PMhNYujNdlFx44dERUV1WbLt0S4PRRFgdPpNI6CDx8+vMEmOw+ckZ2kp6e36fItFW7g/4/iRHbXlqM2YJEDakQUeAw3kUmKi4vx448/Ys+ePW2yfMv8njvQhL/npiCyYt/m/NxENsXNciKbYriJbIrhJrIphpvIphhuIptiuIlsiuEmsimGm8imGG4im2K4iWyK4SayKYabyKYYbiKbYriJbIrhJrIphpvIphhuIptiuIlsiuEmsimGm8imGG4im2K4iWyK4Sayqf8HdOnkyTSg34EAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 14 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Visualize some examples from the dataset.\n",
    "# We show a few examples of training images from each class.\n",
    "classes = range(2)\n",
    "num_classes = len(classes)\n",
    "samples_per_class = 7\n",
    "for y, cls in enumerate(classes):\n",
    "    idxs = np.flatnonzero(labels == y)\n",
    "    idxs = np.random.choice(idxs, samples_per_class, replace=False)\n",
    "    for i, idx in enumerate(idxs):\n",
    "        plt_idx = i * num_classes + y + 1\n",
    "        plt.subplot(samples_per_class, num_classes, plt_idx)\n",
    "        plt.imshow(imgs[idx].reshape(28,28).astype('uint8'))\n",
    "        plt.axis('off')\n",
    "        if i == 0:\n",
    "            plt.title(cls)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(28000L, 785L)\n",
      "(28000L,)\n"
     ]
    }
   ],
   "source": [
    "print(X_train.shape)\n",
    "print(y_train.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "iteration 0 / 500: loss 0.702453\n",
      "iteration 100 / 500: loss 0.182190\n",
      "iteration 200 / 500: loss 0.180627\n",
      "iteration 300 / 500: loss 0.108271\n",
      "iteration 400 / 500: loss 0.131198\n"
     ]
    }
   ],
   "source": [
    "from DSVC.classifiers import LogisticRegression\n",
    "\n",
    "# Start training. \n",
    "# You should open DSVC/classifiers/logistic_regression.py and implement the function.\n",
    "# Then run this cell.\n",
    "\n",
    "classifier = LogisticRegression()\n",
    "loss_history = classifier.train(\n",
    "    X_train_feats, \n",
    "    y_train,\n",
    "    learning_rate = 1e-3,\n",
    "    num_iters = 500,\n",
    "    batch_size = 64,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0xeb652b0>]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(loss_history)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The accuracy socre is  0.9760714285714286\n"
     ]
    }
   ],
   "source": [
    "y_test_pred = classifier.predict(X_test_feats)\n",
    "print \"The accuracy socre is \", np.mean(y_test == y_test_pred)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "you should get the accuracy higher than 96%.\n",
    "\n",
    "----\n",
    "\n",
    "### F1-Measure\n",
    "Notice that, if our model always output '1', totally ignoring the input X, we can get a accuracy 90%.So, in this assignment, accuracy is not efficient enough. \n",
    "\n",
    "We will use F1-Measure to evaluate our model.\n",
    "\n",
    "You may need this:\n",
    "[F1-Measure](https://baike.baidu.com/item/f-measure/913107?fr=aladdin)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n",
      "1.0\n",
      "F1: 1.0\n"
     ]
    }
   ],
   "source": [
    "# Calculate the precision(准确率), recall(召回率) and F1\n",
    "# important： We should consider label '0' as 'positive' here. \n",
    "# That means 'True positive' ==> '(y_test == 0) and (y_test_pred == 0)'\n",
    "\n",
    "#######Your code here########\n",
    "\n",
    "TP = 0.0\n",
    "TN = 0.0\n",
    "FP = 0.0\n",
    "FN = 0.0\n",
    "\n",
    "#compute TP，将正类预测为正类数\n",
    "for i in range(785):\n",
    "    if y_test_pred[i] == 0 and y_test[i] == 0:\n",
    "        TP += 1.0\n",
    "\n",
    "\n",
    "#compute TN，将负类预测为负类数\n",
    "for i in range(785):\n",
    "    if y_test_pred[i] == 1 and y_test[i] == 1:\n",
    "        TP += 1.0\n",
    "        \n",
    "        \n",
    "#compute FP，将负类预测为正类数\n",
    "for i in range(785):\n",
    "    if y_test_pred[i] == 0 and y_test[i] == 1:\n",
    "        TP += 1.0\n",
    "        \n",
    "\n",
    "#compute FN，将正类预测为负类数\n",
    "for i in range(785):\n",
    "    if y_test_pred[i] == 1 and y_test[i] == 0:\n",
    "        TP += 1.0\n",
    "        \n",
    "        \n",
    "#compute precision,准确率\n",
    "precision = TP / (TP + FP)\n",
    "#compute recall,召回率\n",
    "recall = TP / (TP + FN)\n",
    "print precision\n",
    "print recall\n",
    "print 'F1:', precision*recall*2/(precision+recall)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "you should get the F1 higher than 85%."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multiclass classification\n",
    "\n",
    "Now, we use the Logistic Regression to classification handwritten digits. There are 10 class, from '0' to '9'.\n",
    "\n",
    "\n",
    "Hint: The method \"one vs all\" may helpful. [Here is the introduction to \"one vs all\"](https://msdn.microsoft.com/library/en-us/Dn905887.aspx). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(28000L, 785L)\n",
      "(14000L, 785L)\n"
     ]
    }
   ],
   "source": [
    "# Read the data for you\n",
    "data = pd.read_csv('./DSVC/datasets/MNIST.csv',header=0).values # change the path by yourself\n",
    "imgs = data[0::,1::]\n",
    "labels = data[::,0]\n",
    "        \n",
    "# 2/3 training set\n",
    "# 1/3 test set\n",
    "split_index = len(labels) * 2 / 3\n",
    "X_train = imgs[:split_index]\n",
    "y_train = labels[:split_index]\n",
    "X_test = imgs[split_index:]\n",
    "y_test = labels[split_index:]\n",
    "\n",
    "X_train = np.hstack([X_train, np.ones((X_train.shape[0], 1))])\n",
    "X_test = np.hstack([X_test, np.ones((X_test.shape[0], 1))])\n",
    "\n",
    "print X_train.shape\n",
    "print X_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train_feats = None # choose and extract features\n",
    "X_test_feats = None # choose and extract features\n",
    "X_train_feats = (X_train - np.mean(X_train)) / np.std(X_train)#(x - 平均值) / 标准差\n",
    "X_test_feats = (X_test - np.mean(X_test)) / np.std(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "i= 0\n",
      "iteration 0 / 500: loss 0.710804\n",
      "iteration 100 / 500: loss 0.162376\n",
      "iteration 200 / 500: loss 0.152253\n",
      "iteration 300 / 500: loss 0.101026\n",
      "iteration 400 / 500: loss 0.123984\n",
      "i= 1\n",
      "iteration 0 / 500: loss 0.695804\n",
      "iteration 100 / 500: loss 0.153009\n",
      "iteration 200 / 500: loss 0.189862\n",
      "iteration 300 / 500: loss 0.134026\n",
      "iteration 400 / 500: loss 0.126817\n",
      "i= 2\n",
      "iteration 0 / 500: loss 0.692241\n",
      "iteration 100 / 500: loss 0.316229\n",
      "iteration 200 / 500: loss 0.177907\n",
      "iteration 300 / 500: loss 0.196101\n",
      "iteration 400 / 500: loss 0.158256\n",
      "i= 3\n",
      "iteration 0 / 500: loss 0.688668\n",
      "iteration 100 / 500: loss 0.252713\n",
      "iteration 200 / 500: loss 0.364761\n",
      "iteration 300 / 500: loss 0.293301\n",
      "iteration 400 / 500: loss 0.196807\n",
      "i= 4\n",
      "iteration 0 / 500: loss 0.696254\n",
      "iteration 100 / 500: loss 0.149448\n",
      "iteration 200 / 500: loss 0.281268\n",
      "iteration 300 / 500: loss 0.203704\n",
      "iteration 400 / 500: loss 0.153328\n",
      "i= 5\n",
      "iteration 0 / 500: loss 0.685809\n",
      "iteration 100 / 500: loss 0.178692\n",
      "iteration 200 / 500: loss 0.160908\n",
      "iteration 300 / 500: loss 0.276239\n",
      "iteration 400 / 500: loss 0.169613\n",
      "i= 6\n",
      "iteration 0 / 500: loss 0.686712\n",
      "iteration 100 / 500: loss 0.316521\n",
      "iteration 200 / 500: loss 0.161274\n",
      "iteration 300 / 500: loss 0.157427\n",
      "iteration 400 / 500: loss 0.170379\n",
      "i= 7\n",
      "iteration 0 / 500: loss 0.690097\n",
      "iteration 100 / 500: loss 0.276465\n",
      "iteration 200 / 500: loss 0.238689\n",
      "iteration 300 / 500: loss 0.117647\n",
      "iteration 400 / 500: loss 0.123280\n",
      "i= 8\n",
      "iteration 0 / 500: loss 0.696296\n",
      "iteration 100 / 500: loss 0.366579\n",
      "iteration 200 / 500: loss 0.311402\n",
      "iteration 300 / 500: loss 0.223864\n",
      "iteration 400 / 500: loss 0.250939\n",
      "i= 9\n",
      "iteration 0 / 500: loss 0.688159\n",
      "iteration 100 / 500: loss 0.233891\n",
      "iteration 200 / 500: loss 0.349694\n",
      "iteration 300 / 500: loss 0.172961\n",
      "iteration 400 / 500: loss 0.213126\n"
     ]
    }
   ],
   "source": [
    "# Start training. \n",
    "# You should update your code in DSVC/classifiers/logistic_regression.py .\n",
    "# Then run this cell.\n",
    "\n",
    "classifier = LogisticRegression()\n",
    "classifier.one_vs_all(\n",
    "    X_train_feats, \n",
    "    y_train,\n",
    "    learning_rate = 1e-3,\n",
    "    num_iters = 500,\n",
    "    batch_size = 64,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The accruacy socre is  0.8347142857142857\n"
     ]
    }
   ],
   "source": [
    "# you may change your code in function `predict`\n",
    "y_test_pred = classifier.one_vs_all_predict(X_test_feats)\n",
    "print \"The accruacy socre is \", np.mean(y_test == y_test_pred)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 27",
   "language": "python",
   "name": "python27"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
